 function Module()
{

	this.version = null;
	this.type = null;  //Possible values -> "fund" || "quote" || "monitor"
	this.quoteHistorySourceURL = null;
	this.quoteNameSourceURL = null;
	this.moduleHostURL = null;
	this.configuration = null;
	this.content = null;
 	this.id = null;
	this.updateTime = 0;
	this.mode=null;
	this.marketClosed;

	this.messageManager=null;
	this.tabsManager = null;

	this.investedValues= null;

	this.getLastInvestment = getLastInvestment;
	this.getFirstInvestment = getFirstInvestment;
	this.getInvestmentValue = getInvestmentValue;
	this.getCurrentInvestmentValue = getCurrentInvestmentValue;
	this.getTotalInvested = getTotalInvested;
	this.getPurchasedQuantity = getPurchasedQuantity;

	this.loadModuleProperties = null;
	this.checkModuleInitialized = null;
	this.printHowTo = null;
	this.getChatUrl = null;

 	this.fireQuotationDataLoaded = null;


	// To be implemtned yet.. Regarding a new edit form approach
	this.setModuleProperties = null;
}

function Fund()
{
  this.name="";
  this.quotes=new Array();
}

function Quote(symbol, percent)
{
  this.name ="";
  this.stockExchange = null;
  this.symbol = symbol;
  this.compositionPercent= percent;
  this.cotations = new Array();
  this.currentCotation = null;
  this.getCotation = getCotation;
  this.getLoadedCotationsQtd = getLoadedCotationsQtd;

}

function Cotation(date,value)
{
  this.date = date;
  this.value = value;
}

function InvestedValue(date, value)
{
  this.date = date;
  this.value = value;
  this.quotesData = new Array();
  this.addQuoteData = addQuoteData;

}



function QuoteData(_quote,_cotation, _addCotationIntoQuoteHistory)
{
  this.quote = _quote;
  this.cotation = _cotation;
  this.setPurchasedQuantity = setPurchasedQuantity;
  this.purchasedQuantity = 0;

  if(_addCotationIntoQuoteHistory == null)
  	_addCotationIntoQuoteHistory = true;

  if(_addCotationIntoQuoteHistory && (this.quote.getCotation(this.cotation.date)== null))
  {
  	this.quote.cotations.push(this.cotation);
  }
}

function Configuration()
{
  this.quoteHistorySourceURL = "";
  this.quoteNameSourceURL = "";
  this.moduleHostURL = "";
  this.quoteURL = "";
  this.chartURL = "";

  this.chart_timeDuration = 0;
  this.chart_timeUnit = null;

  this.history_numRecords = 0;
  this.history_percentBaseMode = "";
  this.history_percentBaseDate = null;
  this.thresholdBuy = 0;
  this.thresholdSell = 0;
  this.chartZoomHeader = null;

}


function setPurchasedQuantity(_investedValue)
 {

  var realValue = _investedValue * this.quote.compositionPercent / 100;

  this.purchasedQuantity = realValue / this.cotation.value;

 }

function addQuoteData(_quote, _cotation, _includeHistory)
{
	if(_includeHistory ==null)
		{
			_includeHistory=true;
		}

	var quoteData = new QuoteData(_quote,_cotation, _includeHistory);
	quoteData.setPurchasedQuantity(this.value);
	this.quotesData.push(quoteData);
	return quoteData;

}

function getLastInvestment()
{
	var investedRes = null;
	var qtdInvestments = 0;
	var invested;

	if(this.investedValues!=null)
	{
		investedRes = this.investedValues[0];
		qtdInvestments = this.investedValues.length;
	}

	for( var  i=1;i<qtdInvestments;i++)
	{
		invested = this.investedValues[i];
		if(investedRes.date < invested.date)
		   investedRes = invested;
	}

	return investedRes;

}

function getFirstInvestment()
{
	var investedRes = this.investedValues[0];
	var invested;

	for( var  i=1;i<this.investedValues.length;i++)
	{
		invested = this.investedValues[i];
		if(investedRes.date > invested.date)
		   investedRes = invested;
	}

	return investedRes;


}

function getTotalInvested(_date)
{
	var val = 0;
	var i;
	if(_date==null)
		_date = new Date();

	for( i=0;i<this.investedValues.length;i++)
	{
		if(_date.getTime() >= this.investedValues[i].date.getTime())
		{
			val += this.investedValues[i].value;
		}

	}

	return val;
}



/**
 *
 * @param {Object} _quoteSymbol
 * @param {Object} _date --> if _date ==null, this fucntion will return all the quantity until today
 * otherwise it will load the quantity until this date
 *
 */
function getPurchasedQuantity(_quoteSymbol, _date)
{
	var quantity = 0;
	var date;
	var invested;

	if(_date ==null)
		_date = new Date();

	date = getValidDate(_date);

	for( var  i=0;i<this.investedValues.length;i++)
	{
		invested = this.investedValues[i];
		if(date.getTime() >= invested.date.getTime())
		{
			for( var j=0;j<invested.quotesData.length;j++)
			{
				if(invested.quotesData[j].quote.symbol==_quoteSymbol)
				{
					quantity += invested.quotesData[j].purchasedQuantity;
				}
			}
		}

	}

	return quantity;
}

function getInvestmentValue(_date)
{
	var finalValue = 0; //there is no cotation loaded for this date
	var cotation = null;
	var quantity;
	var date = getValidDate(_date);
	var quotes;

	if(this.type=="fund")
	{
		quotes = this.fund.quotes;
	}
	else if(this.type=="quote")
	{
		quotes = new Array();
		quotes.push(this.quote);
	}

	for( var i=0;i<quotes.length;i++)
	{
		quantity = this.getPurchasedQuantity(quotes[i].symbol, date);
		cotation = quotes[i].getCotation(date);
		if(cotation !=null)
			finalValue += quantity * cotation.value;
		else
			{
				finalValue = null;
				break;
			}
	}

	return finalValue;
}

function getCurrentInvestmentValue()
{
	return this.getInvestmentValue(new Date());
}

function getCotation(_date)
{
	var cotationRes = null;
	for( var i=0;i<this.cotations.length; i++)
	{
		if(this.cotations[i].date.getTime() == _date.getTime())
		{
			cotationRes = this.cotations[i];
			break;
		}
	}

	if(cotationRes==null)
	{
		if(this.currentCotation!=null && this.currentCotation.date.getTime() <= _date.getTime())
		{
			cotationRes = this.currentCotation;
		}
	}

	return cotationRes;
}

/**
 * It is assumed that the array is sorted in a descrecent way by date
 * @param {Object} _quote
 * @param {Object} _dateIni
 * @param {Object} _dateFim
 */
function getLoadedCotationsQtd(_dateIni, _dateFim)
{
	var recordsQtd = -1;
	var started = false;
	var cotation;

	for(var i=0;i<this.cotations.length;i++)
	{
		cotation = this.cotations[i];
		if(started) recordsQtd++;

		if(!started && (_dateFim.getTime()>= cotation.date.getTime()))
		{
			started = true;
			recordsQtd = 1;
		}

		if(_dateIni.getTime() == cotation.date.getTime() )
		{
			break;
		}

		if(_dateIni.getTime() > cotation.date.getTime() )
		{
			recordsQtd--;
			break;
		}
	}


	return recordsQtd;

}

